// import ffi from "ffi-napi"
// import ref from "ref-napi"
const ffi = require("ffi-napi")
const ref = require("ref-napi")


// 加载dll
const dll_path = "E:\\workspace\\Cpp\\FHESearchOnEncryptedData\\x64\\Debug"
const dll = ffi.Library(`${dll_path}/FHESED4Customer.dll`, {
    dll_example: [ref.types.int, [ref.types.int]],
    read_aes_ecb_sk: [ref.refType(ref.types.char), [ref.refType(ref.types.char), ref.refType(ref.types.char), ref.refType(ref.types.int)]],
    aes_ecb_enc_utf8str: [ref.refType(ref.types.char), [ref.refType(ref.types.char), ref.refType(ref.types.char), ref.refType(ref.types.int)]],
    aes_ecb_dec_utf8str: [ref.refType(ref.types.char), [ref.refType(ref.types.char), ref.refType(ref.types.char), ref.refType(ref.types.int)]],
    gen_aes_index:[ref.types.int, [ref.refType(ref.types.char), ref.types.int]],
    aes_ecb_enc_integer: [ref.refType(ref.types.char), [ref.types.int, ref.refType(ref.types.char), ref.refType(ref.types.int)]],
    aes_ecb_dec_integer: [ref.types.int, [ref.refType(ref.types.char)]],
    
    read_soft_enc_pk: [ref.refType(ref.types.char), [ref.refType(ref.types.char), ref.refType(ref.types.char), ref.refType(ref.types.int)]],
    fhe_soft_enc_utf8str: [ref.refType(ref.types.char), [ref.refType(ref.types.char), ref.refType(ref.types.char), ref.refType(ref.types.int)]],
});
// 读取AES密钥
const aes_ecb_sk_file_path = "E:\\workspace\\Cpp\\FHESearchOnEncryptedData\\key\\huangheng20231101_aes_ecb_sk.txt"
const aes_ecb_sk_file_path_buf = ref.allocCString(aes_ecb_sk_file_path);
const read_aes_ecb_sk_res = Buffer.alloc(100);
const read_aes_ecb_sk_res_length = ref.alloc(ref.types.int);
dll.read_aes_ecb_sk(aes_ecb_sk_file_path_buf, read_aes_ecb_sk_res, read_aes_ecb_sk_res_length);
// console.log("read_aes_ecb_sk_res", read_aes_ecb_sk_res.toString())
// console.log("read_aes_ecb_sk_res_length", read_aes_ecb_sk_res_length.deref())
// 读取同态公钥
const fhe_pk_file_path = "E:\\workspace\\Cpp\\FHESearchOnEncryptedData\\key\\huangheng20231023_pk_key.txt"
const fhe_pk_file_path_buf = ref.allocCString(fhe_pk_file_path);
const read_soft_enc_pk_res = Buffer.alloc(100);
const read_soft_enc_pk_res_length = ref.alloc(ref.types.int);
dll.read_soft_enc_pk(fhe_pk_file_path_buf, read_soft_enc_pk_res, read_soft_enc_pk_res_length);
// console.log("read_soft_enc_pk_res", read_soft_enc_pk_res.toString())
// console.log("read_soft_enc_pk_res_length", read_soft_enc_pk_res_length.deref())


// 封装 AES ECB 加密函数
function aesEncryptUtf8String(plaintext) {
    const inputBuffer = ref.allocCString(plaintext, "utf8")
    const inputBufferLength = inputBuffer.length;
    const outputBufferLength = (Math.floor(inputBufferLength/16)+1)*32;
    const outputBuffer = Buffer.alloc(outputBufferLength); // 适当设置缓冲区大小
    const outputLength = ref.alloc(ref.types.int);
    dll.aes_ecb_enc_utf8str(inputBuffer, outputBuffer, outputLength);
    return outputBuffer.toString()
}


// 封装 AES ECB 解密函数
function aesDecryptUtf8String(aes_ciphertext) {
    const inputBuffer = ref.allocCString(aes_ciphertext, 'utf8');
    const outputBufferLength = Math.floor(inputBuffer.length/2);
    const outputBuffer = Buffer.alloc(outputBufferLength); // 适当设置缓冲区大小
    const outputLength = ref.alloc(ref.types.int);
    dll.aes_ecb_dec_utf8str(inputBuffer, outputBuffer, outputLength);
    return outputBuffer.toString().replace(/\x00/g, '');
}

function genAesIndex8(plaintext){
    const inputBuffer = ref.allocCString(plaintext, "utf8")
    return dll.gen_aes_index(inputBuffer, 8)
}

function aesEncryptInteger(plain_integer){
    const outputBufferLength = 32;
    const outputBuffer = Buffer.alloc(outputBufferLength); // 适当设置缓冲区大小
    const outputLength = ref.alloc(ref.types.int);
    dll.aes_ecb_enc_integer(plain_integer, outputBuffer, outputLength);
    return outputBuffer.toString()
}

function aesDecryptInteger(aes_ciphertext){
    const inputBuffer = ref.allocCString(aes_ciphertext, 'utf8');
    return dll.aes_ecb_dec_integer(inputBuffer);
}

function fheSoftEncUtf8str(plaintext){
    const inputBuffer = ref.allocCString(plaintext, "utf8")
    const outputBufferLength = plaintext.length * 256;
    const outputBuffer = Buffer.alloc(outputBufferLength); // 适当设置缓冲区大小
    const outputLength = ref.alloc(ref.types.int);
    dll.fhe_soft_enc_utf8str(inputBuffer, outputBuffer, outputLength);
    return outputBuffer.toString()
}
// const plaintext = "中国国人最棒了！！"
// const aes_ciphertext = aesEncryptUtf8String(plaintext)
// const aes_dec_plaintext = aesDecryptUtf8String(aes_ciphertext)
// console.log(aes_ciphertext)
// console.log(aes_dec_plaintext)
// console.log(genAesIndex(plaintext))
// console.log(aesEncryptInteger(123456789))
// console.log(aesDecryptInteger(aesEncryptInteger(123456789)))
// console.log(fheSoftEncUtf8str(plaintext))

module.exports = {
    aesEncryptUtf8String,
    aesDecryptUtf8String,
    genAesIndex8,
    aesEncryptInteger,
    aesDecryptInteger,
    fheSoftEncUtf8str,
}